home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 March / CMCD0305.ISO / Software / Freeware / Programare / nvu / nvu-0.80-win32-installer-full.exe / {app} / chrome / cascades.jar / content / cascades / commonCssProps.js < prev    next >
Text File  |  2004-03-09  |  45KB  |  1,257 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Mozilla Public License Version
  5.  * 1.1 (the "License"); you may not use this file except in compliance with
  6.  * the License. You may obtain a copy of the License at
  7.  * http://www.mozilla.org/MPL/
  8.  *
  9.  * Software distributed under the License is distributed on an "AS IS" basis,
  10.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.  * for the specific language governing rights and limitations under the
  12.  * License.
  13.  *
  14.  * The Original Code is CaScadeS, a stylesheet editor for Composer.
  15.  *
  16.  * The Initial Developer of the Original Code is
  17.  * Daniel Glazman.
  18.  * Portions created by the Initial Developer are Copyright (C) 2002
  19.  * the Initial Developer. All Rights Reserved.
  20.  *
  21.  * Contributor(s):
  22.  *   Original author: Daniel Glazman <daniel@glazman.org>
  23.  *   Charley Manske <cmanske@netscape.com>, for local fonts access
  24.  *
  25.  * Alternatively, the contents of this file may be used under the terms of
  26.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  27.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28.  * in which case the provisions of the GPL or the LGPL are applicable instead
  29.  * of those above. If you wish to allow use of your version of this file only
  30.  * under the terms of either the GPL or the LGPL, and not to allow others to
  31.  * use your version of this file under the terms of the MPL, indicate your
  32.  * decision by deleting the provisions above and replace them with the notice
  33.  * and other provisions required by the GPL or the LGPL. If you do not delete
  34.  * the provisions above, a recipient may use your version of this file under
  35.  * the terms of any one of the MPL, the GPL or the LGPL.
  36.  *
  37.  * ***** END LICENSE BLOCK ***** */
  38.  
  39. var gTimerID;
  40. var textColor, backgroundColor, borderColor;
  41. var gLocalFonts = null;
  42. const kUrlString = "url(";
  43.  
  44.  
  45. // * if |value| is not empty, sets the CSS property |property| to |value|
  46. //   in |elt| element's inline styles ; otherwise removes the property
  47. //   param XULElement elt
  48. //   param String property
  49. //   param String value
  50. function AddStyleToElement(elt, property, value)
  51. {
  52.   if (!elt || !elt.style) return;
  53.   if (value == "") {
  54.     elt.style.removeProperty(property);
  55.   }
  56.   else {
  57.     try {
  58.       elt.style.setProperty(property, value,
  59.                             elt.style.getPropertyPriority(property));
  60.     }
  61.     catch (ex) {  }
  62.   }
  63. }
  64.  
  65. // * Callback from font-family selection XUL elts
  66. //   param String fontFamily
  67. function onFontFamilySelect(fontFamily)
  68. {
  69.   if (!gDialog.selectedObject) return;
  70.   var enableCustomInput = false;
  71.   var enablePredefMenu  = false;
  72.   if (fontFamily == "") {
  73.     // nothing to do here
  74.   }
  75.   else if (fontFamily == "-user-defined") {
  76.     // user wants to select a font that is not pre-defined
  77.     // so let's get that user defined name from the textarea
  78.     enableCustomInput = true;
  79.     fontFamily = gDialog.customFontFamilyInput.value;
  80.   }
  81.   else if (fontFamily == "-predefined"){
  82.     fontFamily = "";
  83.     enablePredefMenu = true;
  84.     // user wants a predefined font family
  85.     var valueElt = gDialog.predefFontFamilyMenulist.selectedItem;
  86.     if (valueElt) {
  87.       fontFamily = valueElt.value;
  88.     }
  89.   }
  90.   else {
  91.     // all other cases are user defined fonts
  92.     enablePredefMenu = true;
  93.   }
  94.  
  95.   EnableUI(gDialog.predefFontFamilyMenulist, enablePredefMenu);
  96.   EnableUI(gDialog.customFontFamilyInput, enableCustomInput);
  97.  
  98.   AddStyleToElement(gDialog.brownFoxLabel,  "font-family", fontFamily);
  99.   AddStyleToElement(gDialog.selectedObject, "font-family", fontFamily);
  100.   
  101.   SetModifiedFlagOnStylesheet();
  102. }
  103.  
  104. // * Callback when the color textarea's value is changed
  105. //   it sets the correspondinf property/value on the element elt
  106. //   and sets the color of the corresponding UI button
  107. //   param XULElement elt
  108. //   param String property
  109. //   param String id
  110. //   param String ColorWellID
  111. function onColorZoneInput(elt, property, id, ColorWellID)
  112. {
  113.   ChangeValueOnInput(elt, property, id);
  114.   setColorWell(ColorWellID, elt.value);
  115. }
  116.  
  117. // * Opens a color picker for the requested property and handles
  118. //   the result
  119. //   param String ColorWellID
  120. function GetColorAndUpdate(ColorWellID)
  121. {
  122.   var colorObj = new Object;
  123.   var colorWell = document.getElementById(ColorWellID);
  124.   if (!colorWell) return;
  125.  
  126.   // Don't allow a blank color, i.e., using the "default"
  127.   colorObj.NoDefault = true;
  128.  
  129.   switch( ColorWellID )
  130.   {
  131.     case "textCW":
  132.       colorObj.Type = "Text";
  133.       colorObj.TextColor = textColor;
  134.       break;
  135.     case "backgroundCW":
  136.       colorObj.Type = "Page";
  137.       colorObj.PageColor = backgroundColor;
  138.       break;
  139.     case "bordertopCW":
  140.     case "borderleftCW":
  141.     case "borderrightCW":
  142.     case "borderbottomCW":
  143.       colorObj.Type = "Text";
  144.       colorObj.TextColor = borderColor;
  145.       break;
  146.   }
  147.  
  148.   window.openDialog("chrome://editor/content/EdColorPicker.xul", "_blank", "chrome,close,titlebar,modal", "", colorObj);
  149.  
  150.   // User canceled the dialog
  151.   if (colorObj.Cancel)
  152.     return;
  153.  
  154.   var color = "";
  155.   var property = "";
  156.   var textZone = null;
  157.   switch( ColorWellID )
  158.   {
  159.     case "textCW":
  160.       color = textColor = colorObj.TextColor;
  161.       property = "color";
  162.       AddStyleToElement(gDialog.brownFoxLabel, "color", color);
  163.       textZone = gDialog.textColorInput;
  164.       break;
  165.     case "backgroundCW":
  166.       color = backgroundColor = colorObj.BackgroundColor;
  167.       property = "background-color";
  168.       textZone = gDialog.backgroundColorInput;
  169.       break;
  170.     case "bordertopCW":
  171.       color = textColor = colorObj.TextColor;
  172.       property = "border-top-color";
  173.       AddStyleToElement(gDialog.borderPreview, "border-top-color", color);
  174.       textZone = gDialog.topBorderColorInput;
  175.       break;
  176.     case "borderleftCW":
  177.       color = textColor = colorObj.TextColor;
  178.       property = "border-left-color";
  179.       AddStyleToElement(gDialog.borderPreview, "border-left-color", color);
  180.       textZone = gDialog.leftBorderColorInput;
  181.       break;
  182.     case "borderrightCW":
  183.       color = textColor = colorObj.TextColor;
  184.       property = "border-right-color";
  185.       AddStyleToElement(gDialog.borderPreview, "border-right-color", color);
  186.       textZone = gDialog.rightBorderColorInput;
  187.       break;
  188.     case "borderbottomCW":
  189.       color = textColor = colorObj.TextColor;
  190.       property = "border-bottom-color";
  191.       AddStyleToElement(gDialog.borderPreview, "border-bottom-color", color);
  192.       textZone = gDialog.bottomBorderColorInput;
  193.       break;
  194.   }
  195.  
  196.   setColorWell(ColorWellID, color); 
  197.   if (textZone != null) {
  198.     textZone.value = color;
  199.     if (ColorWellID == "bordertopCW")
  200.       IfFourSidesSameStyle('border', 'color', color, 'allFourBordersSame', 'borderPreview', null);
  201.     else if (ColorWellID == "backgroundCW")
  202.       AddStyleToElement(gDialog.backgroundPreview, "background-color", color);
  203.   }
  204.   try {
  205.     gDialog.selectedObject.style.setProperty(property,
  206.                               color,
  207.                               gDialog.selectedObject.style.getPropertyPriority(property));
  208.   }
  209.   catch (ex) {}
  210.   SetModifiedFlagOnStylesheet();
  211. }
  212.  
  213. // * Callback when a textarea's value is changed
  214. //   it sets the corresponding property/value on the element elt
  215. //   param XULElement elt
  216. //   param String property
  217. //   param String id
  218. function ChangeValueOnInput(elt, property, id)
  219. {
  220.   if (!gDialog.selectedObject) return;
  221.   var value = elt.value;
  222.   if (id != null) {
  223.     elt = document.getElementById(id);
  224.     if (elt) {
  225.       AddStyleToElement(elt, property, value);
  226.     }
  227.   }
  228.   AddStyleToElement(gDialog.selectedObject, property, value);
  229.   SetModifiedFlagOnStylesheet();
  230. }
  231.  
  232. // * Callback when a pulldown menu entry is selected
  233. //   param String property
  234. //   param String value
  235. //   param String id
  236. function onPullDownChanged(property, value, id)
  237. {
  238.   if (!gDialog.selectedObject) return;
  239.   if (id != null) {
  240.     var elt = document.getElementById(id);
  241.     if (elt) {
  242.       AddStyleToElement(elt, property, value);
  243.     }
  244.   }
  245.   AddStyleToElement(gDialog.selectedObject, property, value);
  246.   SetModifiedFlagOnStylesheet();
  247. }
  248.  
  249. // * Callback when the 'none' value is selected for the
  250. //   'text-decoration' property; it unchecks all other checkboxes
  251. //   if the 'none' checkbox is checked
  252. function onNoneTextDecorationChange()
  253. {
  254.   if (!gDialog.selectedObject) return;
  255.  
  256.   var textDecoration = "";
  257.   if (gDialog.noDecorationCheckbox.checked) {
  258.     // uncheck other possible values for the property if 'none' is checked
  259.     gDialog.textUnderlineCheckbox.checked   = false;
  260.     gDialog.textOverlineCheckbox.checked    = false;
  261.     gDialog.textLinethroughCheckbox.checked = false;
  262.     gDialog.textBlinkCheckbox.checked       = false;
  263.     textDecoration = "none";
  264.   }
  265.   AddStyleToElement(gDialog.selectedObject, "text-decoration", textDecoration);
  266.   AddStyleToElement(gDialog.brownFoxLabel, "text-decoration", textDecoration);
  267.   SetModifiedFlagOnStylesheet();
  268. }
  269.     
  270. // * Callback when one of the chekboxes but for 'none' for
  271. //   'text-decoration' property sees his state changed ; it
  272. //   recomputes the value of the property appending the various
  273. //   individual values
  274. function onTextDecorationChange()
  275. {
  276.   if (!gDialog.selectedObject) return;
  277.  
  278.   var textDecoration = "";
  279.   if (gDialog.textUnderlineCheckbox.checked)     textDecoration += "underline ";
  280.   if (gDialog.textOverlineCheckbox.checked)      textDecoration += "overline ";
  281.   if (gDialog.textLinethroughCheckbox.checked)   textDecoration += "line-through ";
  282.   if (gDialog.textBlinkCheckbox.checked)         textDecoration += "blink ";
  283.   if (textDecoration != "") {
  284.     gDialog.noDecorationCheckbox.checked = false;
  285.   }
  286.   AddStyleToElement(gDialog.selectedObject, "text-decoration", textDecoration);
  287.   AddStyleToElement(gDialog.brownFoxLabel, "text-decoration", textDecoration);
  288.   SetModifiedFlagOnStylesheet();
  289. }
  290.  
  291. // * This function sets a timer when the user changes an image URL
  292. //   in a textarea. This leaves the user enough time to complete the
  293. //   URL and avoids Gecko trying to load an incomplete URL
  294. function ChangeImageSrc()
  295. {
  296.   if (gTimerID)
  297.     clearTimeout(gTimerID);
  298.  
  299.   gTimerID = setTimeout("onBgImageUrlChanged()", 800);
  300. }
  301.  
  302. // * This is the callback from ChangeImageSrc(). It loads an image and uses
  303. //   the cache.
  304. function onBgImageUrlChanged()
  305. {
  306.   var property = "background-image";
  307.   var id = "backgroundPreview";
  308.  
  309.   if (!gDialog.selectedObject) return;
  310.   var value = gDialog.backgroundImageInput.value;
  311.   if (value != "" && value != "none") {
  312.     try {
  313.       // Remove the image URL from image cache so it loads fresh
  314.       //  (if we don't do this, loads after the first will always use image cache
  315.       //   and we won't see image edit changes or be able to get actual width and height)
  316.       
  317.       var IOService = GetIOService();
  318.       if (IOService)
  319.       {
  320.         // We must have an absolute URL to preview it or remove it from the cache
  321.         value = MakeAbsoluteUrl(value);
  322.  
  323.         if (GetScheme(value))
  324.         {
  325.           var uri = IOService.newURI(value, null, null);
  326.           if (uri)
  327.           {
  328.             var imgCacheService = Components.classes["@mozilla.org/image/cache;1"].getService();
  329.             var imgCache = imgCacheService.QueryInterface(Components.interfaces.imgICache);
  330.  
  331.             // This returns error if image wasn't in the cache; ignore that
  332.             imgCache.removeEntry(uri);
  333.           }
  334.         }
  335.       }
  336.     } catch(e) {}
  337.     value = kUrlString + value + ")";
  338.   }
  339.   if (id != null) {
  340.     var xulElt = document.getElementById(id);
  341.     if (xulElt) {
  342.       AddStyleToElement(xulElt, property, value);
  343.     }
  344.   }
  345.   AddStyleToElement(gDialog.selectedObject, property, value);
  346.   SetModifiedFlagOnStylesheet();
  347.  
  348.   if (property == "background-image") {
  349.     enableBackgroundProps((value != ""));
  350.   }
  351. }
  352.  
  353. // * This function enable some of the background-* properties that
  354. //   only make sense if there is a background image specified
  355. //   param boolean enable
  356. function enableBackgroundProps(enable)
  357. {
  358.   var idArray = [ "backgroundRepeatLabel", "backgroundRepeatMenulist", "backgroundAttachmentCheckbox",
  359.                    "backgroundPositionLabel", "xBackgroundPositionRadiogroup",
  360.                    "yBackgroundPositionRadiogroup" ];
  361.   var i, elt, lookAtNextSibling;
  362.  
  363.   for (i = 0; i < idArray.length; i++) {
  364.     elt = document.getElementById(idArray[i]);
  365.     lookAtNextSibling = false;
  366.     if (elt.nodeName.toLowerCase() == "radiogroup") {
  367.       elt = elt.firstChild;
  368.       lookAtNextSibling = true;
  369.     }
  370.     while (elt) {
  371.       EnableUI(elt, enable);
  372.       if (lookAtNextSibling) {
  373.         elt = elt.nextSibling;
  374.       }
  375.       else {
  376.         elt = null;
  377.       }
  378.     }
  379.   }
  380. }
  381.  
  382. // * open a file picker dialog for the requested file filter and
  383. //   returns the corresponding file URL into the element of ID id
  384. //   param String filterType
  385. //   param String id
  386. function chooseFile(filterType, id)
  387. {
  388.   // Get a local image file, converted into URL format
  389.   var fileName = GetLocalFileURL(filterType);
  390.   var elt = document.getElementById(id);
  391.   if (fileName)
  392.   {
  393.     // Always try to relativize local file URLs
  394.     if (gHaveDocumentUrl)
  395.       fileName = MakeRelativeUrl(fileName);
  396.  
  397.     elt.value = fileName;
  398.     onBgImageUrlChanged();
  399.   }
  400.   SetTextboxFocus(elt);
  401. }
  402.  
  403. // * Callback when the user changes the value for background-attachment
  404. function onBackgroundAttachmentChange()
  405. {
  406.   if (!gDialog.selectedObject) return;
  407.   // the checkbox is checked if the background scrolls with the page
  408.   var value = gDialog.backgroundAttachmentCheckbox.checked ? "" : "fixed";
  409.   AddStyleToElement(gDialog.selectedObject, "background-attachment", value);
  410.   SetModifiedFlagOnStylesheet();
  411. }
  412.  
  413. // * Callback when one of the background positions (x or y) is changed
  414. function onBackGroundPositionSelect()
  415. {
  416.   var xPosition = gDialog.xBackgroundPositionRadiogroup.selectedItem.value;
  417.   var yPosition = gDialog.yBackgroundPositionRadiogroup.selectedItem.value;
  418.   var value = xPosition + " " + yPosition;
  419.   AddStyleToElement(gDialog.backgroundPreview, "background-position", value);
  420.   AddStyleToElement(gDialog.selectedObject, "background-position", value);
  421.   SetModifiedFlagOnStylesheet();
  422. }
  423.  
  424. // * Inits the values shown in the Text tab panel
  425. function InitTextTabPanel()
  426. {
  427.   gDialog.selectedTab = TEXT_TAB;
  428.   if (!gDialog.selectedObject || !gDialog.selectedObject.style)
  429.     return;
  430.  
  431.   /* INIT FONT-FAMILY */
  432.   var fontFamily       = getSpecifiedStyle("font-family");
  433.   AddStyleToElement(gDialog.brownFoxLabel, "font-family", fontFamily);
  434.   var fontFamilyChoice = "noFontFamilyRadio";
  435.   var predefFontFamilyChoice = "";
  436.   var enableCustomInput = false;
  437.   var enablePredefMenu  = false;
  438.  
  439.  
  440.   if (fontFamily == "arial,helvetica,sans-serif") {
  441.     fontFamilyChoice = "predefFontFamilyRadio";
  442.     predefFontFamilyChoice = "sansSerifFontFamilyMenuitem";
  443.     enablePredefMenu = true;
  444.   }
  445.   else if (fontFamily == "times new roman,times,serif") {
  446.     fontFamilyChoice = "predefFontFamilyRadio";
  447.     predefFontFamilyChoice = "serifFontFamilyMenuitem";
  448.     enablePredefMenu = true;
  449.   }
  450.   else if (fontFamily == "courier new,courier,monospace") {
  451.     fontFamilyChoice = "predefFontFamilyRadio";
  452.     predefFontFamilyChoice = "monospaceFontFamilyMenuitem";
  453.     enablePredefMenu = true;
  454.   }
  455.   else if (fontFamily != "") {
  456.     fontFamilyChoice = "customFontFamilyRadio";
  457.     gDialog.customFontFamilyInput.value = fontFamily;
  458.     enableCustomInput = true;
  459.   }
  460.   /* selects the radio button */
  461.   var fontFamilyItem = document.getElementById(fontFamilyChoice);
  462.   gDialog.fontFamilyRadiogroup.selectedItem = fontFamilyItem;
  463.   /* enablers/disablers */
  464.   if (enablePredefMenu) {
  465.     gDialog.predefFontFamilyMenulist.removeAttribute("disabled");
  466.   }
  467.   else {
  468.     gDialog.predefFontFamilyMenulist.setAttribute("disabled", "true");
  469.   }
  470.   if (enableCustomInput) {
  471.     gDialog.customFontFamilyInput.removeAttribute("disabled");
  472.   }
  473.   else {
  474.     gDialog.customFontFamilyInput.setAttribute("disabled", "true");
  475.   }
  476.  
  477.   if (predefFontFamilyChoice != "") {
  478.     var predefFontFamilyMenuitem = document.getElementById(predefFontFamilyChoice);
  479.     gDialog.predefFontFamilyMenulist.selectedItem = predefFontFamilyMenuitem;
  480.   }
  481.  
  482.   /* INIT COLOR */
  483.   textColor = ConvertRGBColorIntoHEXColor(getSpecifiedStyle("color"));
  484.   backgroundColor = ConvertRGBColorIntoHEXColor(getSpecifiedStyle("background-color"));
  485.   gDialog.textColorInput.setAttribute("value", textColor);
  486.   AddStyleToElement(gDialog.brownFoxLabel, "color", textColor);
  487.   if (backgroundColor == "")
  488.     backgroundColor = "white";
  489.   AddStyleToElement(gDialog.brownFoxLabel, "background-color", backgroundColor);
  490.   setColorWell("textCW", textColor); 
  491.  
  492.   /* INIT FONT-STYLE */
  493.   SelectsOneChoice("font-style", "fontStyleMenulist", "FontStyleMenu", gDialog.brownFoxLabel)
  494.  
  495.   /* INIT FONT-WEIGHT */
  496.   SelectsOneChoice("font-weight", "fontWeightMenulist", "FontWeightMenu", gDialog.brownFoxLabel)
  497.  
  498.   /* INIT TEXT-TRANSFORM */
  499.   SelectsOneChoice("text-transform", "textTransformMenulist", "TextTransformMenu", gDialog.brownFoxLabel)
  500.  
  501.   /* INIT TEXT-ALIGN */
  502.   SelectsOneChoice("text-align", "textAlignMenulist", "TextAlignMenu", gDialog.brownFoxLabel)
  503.  
  504.   /* INIT TEXT-DECORATION */
  505.   var textDecoration = getSpecifiedStyle("text-decoration");
  506.   AddStyleToElement(gDialog.brownFoxLabel, "text-decoration", textDecoration);
  507.   SelectsCheckboxIfValueContains(textDecoration, "underline", "underlineTextDecorationCheckbox");
  508.   SelectsCheckboxIfValueContains(textDecoration, "overline", "overlineTextDecorationCheckbox");
  509.   SelectsCheckboxIfValueContains(textDecoration, "line-through", "linethroughTextDecorationCheckbox");
  510.   SelectsCheckboxIfValueContains(textDecoration, "blink", "blinkTextDecorationCheckbox");
  511.   SelectsCheckboxIfValueContains(textDecoration, "none", "noneTextDecorationCheckbox");
  512.  
  513.   /* INIT FONT SIZE */
  514.   var fontSize = getSpecifiedStyle("font-size");
  515.   if (!fontSize || fontSize == "")
  516.     gDialog.fontSizeInput.value = "";
  517.   else
  518.     gDialog.fontSizeInput.value = fontSize;
  519.   AddStyleToElement(gDialog.brownFoxLabel, "font-size", fontSize);
  520.  
  521.   /* INIT LINE-HEIGHT */
  522.   var lineHeight = getSpecifiedStyle("line-height");
  523.   if (!lineHeight || lineHeight == "")
  524.     gDialog.lineHeightInput.value = "";
  525.   else
  526.     gDialog.lineHeightInput.value = lineHeight;
  527.   
  528. }
  529.  
  530. // * Utility function to check if the four side values of a property
  531. //   are equal so we an show a shorthand in the dialog
  532. //   param String top
  533. //   param String left
  534. //   param String right
  535. //   param String bottom
  536. //   return boolean
  537. function AreAllFourValuesEqual(top, left, right, bottom)
  538. {
  539.   return (top == left && top == right && top == bottom);
  540. }
  541.  
  542. // * Retrieves the specified style for the property |prop| and
  543. //   makes it become the value of the XUL element of ID |id|
  544. //   param String id
  545. //   param String prop
  546. function SetTextzoneValue(id, prop)
  547. {
  548.   var elt = document.getElementById(id);
  549.   if (elt) {
  550.     var value = getSpecifiedStyle(prop);
  551.     if (!value)
  552.       elt.value = "";
  553.     else
  554.       elt.value = value;
  555.   }
  556. }
  557.  
  558. // * Inits the values shown in the Aural tab panel
  559. function InitAuralTabPanel()
  560. {
  561.   gDialog.selectedTab = AURAL_TAB;
  562.   if (!gDialog.selectedObject || !gDialog.selectedObject.style)
  563.     return;
  564.  
  565.   // observe the scrollbar and call onScrollbarAttrModified when an attribute is modified
  566.   gDialog.volumeScrollbar.removeEventListener("DOMAttrModified", onVolumeScrollbarAttrModified, false);
  567.   var volume = getSpecifiedStyle("volume");
  568.   if (volume == "silent") {
  569.     gDialog.muteVolumeCheckbox.checked = true;
  570.     gDialog.volumeScrollbar.setAttribute("disabled", "true");
  571.   }
  572.   else {
  573.     gDialog.muteVolumeCheckbox.checked = false;
  574.     gDialog.volumeScrollbar.removeAttribute("disabled");
  575.   }
  576.   // if no volume specified, display medium value
  577.   if (!volume)
  578.     volume = "50";
  579.   gDialog.volumeMenulist.value = volume;
  580.   UpdateScrollbar(gDialog.volumeMenulist, 'volumeScrollbar');
  581.  
  582.   gDialog.volumeScrollbar.addEventListener("DOMAttrModified", onVolumeScrollbarAttrModified, false);
  583.  
  584.   SelectsOneChoice("speak", "speakMenulist", "SpeakMenu", null);
  585.   SelectsOneChoice("speech-rate", "speechRateMenulist", "SpeechRateMenu", null);
  586. }
  587.  
  588. // * this is a callback of a listener set on the scrollbar for volume setting
  589. //   param DOMMutationEvent aEvent
  590. function onVolumeScrollbarAttrModified(aEvent)
  591. {
  592.   if (aEvent.attrName == "curpos") {
  593.     var e = gDialog.volumeMenulist;
  594.     if (e.value == "silent") return;
  595.     var v = Math.floor(aEvent.newValue / 10);
  596.     e.value = v;
  597.     AddStyleToElement(gDialog.selectedObject, "volume", v);
  598.     SetModifiedFlagOnStylesheet();
  599.   }
  600. }
  601.  
  602. function onOpacityScrollbarAttrModified(aEvent)
  603. {
  604.   if (aEvent.attrName == "curpos") {
  605.     var v = aEvent.newValue / 1000;
  606.     if (v == 1)
  607.       gDialog.opacityLabel.setAttribute("value", "transparent");
  608.     else
  609.       gDialog.opacityLabel.setAttribute("value", v);    
  610.     AddStyleToElement(gDialog.selectedObject, "-moz-opacity", v);
  611.     SetModifiedFlagOnStylesheet();
  612.   }
  613. }
  614.  
  615. // * when the user checks the "mute" checkbox, 'silent' should become
  616. //   the new value of the 'volume' property. If the user unchecks it
  617. //   the value should be computed from the volume scrollbar's position
  618. //   param XULElement elt
  619. function MuteVolume(elt)
  620. {
  621.   var v;
  622.   if (elt.checked) {
  623.     v = "silent";
  624.     gDialog.volumeScrollbar.setAttribute("disable", "true");
  625.   }
  626.   else {
  627.     v = Math.floor(gDialog.volumeScrollbar.getAttribute("curpos") / 10);
  628.     gDialog.volumeScrollbar.removeAttribute("disable");
  629.   }
  630.   gDialog.volumeMenulist.value = v;
  631.   AddStyleToElement(gDialog.selectedObject, "volume", v);
  632.   SetModifiedFlagOnStylesheet();
  633. }
  634.  
  635. // * updates the volume's scrollbar position using the value of the
  636. //   'volume' property stored in the value of the XUL element |elt|.
  637. //   It also converts pre-defined volume names to the equivalent
  638. //   numerical value (defined in CSS 2 spec)
  639. //   param XULElement elt
  640. //   param String id
  641. function UpdateScrollbar(elt, id)
  642. {
  643.   var v = elt.value, x = 0;
  644.   if (v == "silent") return;
  645.   var e = document.getElementById(id);
  646.   switch (v) {
  647.     case "x-soft": x=0; break;
  648.     case "soft":   x=250; break;
  649.     case "medium": x=500; break;
  650.     case "loud":   x=750; break;
  651.     case "x-loud": x=1000; break;
  652.     default:
  653.       x = parseInt(v) * 10;
  654.       // if we don't have a number, it must be a pre-defined keyword
  655.       // and it can't be one because we checked that above
  656.       if (isNaN(x)) x = 0;
  657.       break;
  658.   }
  659.   // let's update the scrollbar's position
  660.   e.setAttribute("curpos",  x);
  661. }
  662.  
  663. // * Inits the values shown in the Box model tab panel
  664. function InitBoxTabPanel()
  665. {
  666.   gDialog.selectedTab = BOX_TAB;
  667.   if (!gDialog.selectedObject || !gDialog.selectedObject.style)
  668.     return;
  669.  
  670.   SelectsOneChoice("display",    "displayMenulist",    "DisplayMenuitem", null);
  671.   SelectsOneChoice("visibility", "visibilityMenulist", "VisibilityMenuitem", null);
  672.   SelectsOneChoice("float",      "floatMenulist",      "FloatMenuitem", null);
  673.   SelectsOneChoice("clear",      "clearMenulist",      "ClearMenuitem", null);
  674.   SelectsOneChoice("position",   "positionMenulist",   "PositionMenuitem", null);
  675.   SelectsOneChoice("overflow",   "overflowMenulist",   "OverflowMenuitem", null);
  676.  
  677.   SetTextzoneValue("zindexInput",                  "z-index");
  678.   SetTextzoneValue("margintopEditableMenulist",    "margin-top");
  679.   SetTextzoneValue("paddingtopEditableMenulist",   "padding-top");
  680.   SetTextzoneValue("topEditableMenulist",          "top");
  681.   SetTextzoneValue("marginleftEditableMenulist",   "margin-left");
  682.   SetTextzoneValue("paddingleftEditableMenulist",  "padding-left");
  683.   SetTextzoneValue("leftEditableMenulist",         "left");
  684.   SetTextzoneValue("marginrightEditableMenulist",  "margin-right");
  685.   SetTextzoneValue("paddingrightEditableMenulist", "padding-right");
  686.   SetTextzoneValue("rightEditableMenulist",        "right");
  687.   SetTextzoneValue("marginbottomEditableMenulist", "margin-bottom");
  688.   SetTextzoneValue("paddingbottomEditableMenulist","padding-bottom");
  689.   SetTextzoneValue("bottomEditableMenulist",       "bottom");
  690.  
  691.   SetTextzoneValue("widthEditableMenulist",        "width");
  692.   SetTextzoneValue("minwidthEditableMenulist",     "min-width");
  693.   SetTextzoneValue("maxwidthEditableMenulist",     "max-width");
  694.   SetTextzoneValue("heightEditableMenulist",       "height");
  695.   SetTextzoneValue("minheightEditableMenulist",    "min-height");
  696.   SetTextzoneValue("maxheightEditableMenulist",    "max-height");
  697.  
  698. }
  699.  
  700. // * Inits the values shown in the Border tab panel
  701. function InitBorderTabPanel()
  702. {
  703.   gDialog.selectedTab = BORDER_TAB;
  704.   if (!gDialog.selectedObject || !gDialog.selectedObject.style)
  705.     return;
  706.  
  707.   /* INIT */
  708.   var style = [ getSpecifiedStyle("border-top-style"),
  709.                 getSpecifiedStyle("border-left-style"),
  710.                 getSpecifiedStyle("border-right-style"),
  711.                 getSpecifiedStyle("border-bottom-style")
  712.               ];
  713.   var width = [ getSpecifiedStyle("border-top-width"),
  714.                 getSpecifiedStyle("border-left-width"),
  715.                 getSpecifiedStyle("border-right-width"),
  716.                 getSpecifiedStyle("border-bottom-width")
  717.               ];
  718.   var color = [ ConvertRGBColorIntoHEXColor(getSpecifiedStyle("border-top-color")),
  719.                 ConvertRGBColorIntoHEXColor(getSpecifiedStyle("border-left-color")),
  720.                 ConvertRGBColorIntoHEXColor(getSpecifiedStyle("border-right-color")),
  721.                 ConvertRGBColorIntoHEXColor(getSpecifiedStyle("border-bottom-color"))
  722.               ];
  723.  
  724.   var sameFourSides = false;
  725.   // let's see if we have same style/color/width for all four borders
  726.   if (AreAllFourValuesEqual(style[0], style[1], style[2], style[3]) &&
  727.       AreAllFourValuesEqual(width[0], width[1], width[2], width[3]) &&
  728.       AreAllFourValuesEqual(getHexColorFromColorName(color[0]),
  729.                             getHexColorFromColorName(color[1]),
  730.                             getHexColorFromColorName(color[2]),
  731.                             getHexColorFromColorName(color[3]))) {
  732.     sameFourSides = true;
  733.   }
  734.  
  735.   var sideArray = [ "top", "left", "right", "bottom" ];
  736.  
  737.   for (var i=0; i<sideArray.length; i++) {
  738.     var styleMenu = document.getElementById( sideArray[i]+"BorderStyleMenulist" );
  739.     var colorInput = document.getElementById( sideArray[i]+"BorderColorInput" );
  740.     var widthInput = document.getElementById( sideArray[i]+"BorderWidthInput" );
  741.     if (!i || !sameFourSides) {
  742.       EnableUI(styleMenu, true);
  743.       EnableUI(colorInput, true);
  744.       EnableUI(widthInput, true);
  745.  
  746.       SelectsOneChoice("border-"+sideArray[i]+"-style",
  747.                        sideArray[i]+"BorderStyleMenulist",
  748.                        sideArray[i]+"BorderStyle", gDialog.borderPreview)
  749.  
  750.       colorInput.value =  color[i];
  751.       setColorWell("border"+sideArray[i]+"CW", color[i]);
  752.  
  753.       AddStyleToElement(gDialog.borderPreview, "border-"+sideArray[i]+"-color", color[i]);
  754.  
  755.       widthInput.value =  width[i];
  756.  
  757.       AddStyleToElement(gDialog.borderPreview, "border-"+sideArray[i]+"-width", width[i]);
  758.     }
  759.     else {
  760.       EnableUI(styleMenu, false);
  761.       EnableUI(colorInput, false);
  762.       EnableUI(widthInput, false);
  763.       colorInput.value = "";
  764.       setColorWell("border"+sideArray[i]+"CW", "");
  765.       widthInput.value = "";
  766.       styleMenu.selectedItem = document.getElementById("unspecified" + sideArray[i] + "BorderStyle");
  767.       AddStyleToElement(gDialog.borderPreview, "border-"+sideArray[i]+"-color", color[0]);
  768.       AddStyleToElement(gDialog.borderPreview, "border-"+sideArray[i]+"-style", style[0]);
  769.       AddStyleToElement(gDialog.borderPreview, "border-"+sideArray[i]+"-width", width[0]);
  770.  
  771.     }
  772.   }
  773.   if (sameFourSides)
  774.     gDialog.allFourBordersSame.setAttribute("checked", "true");
  775.   else
  776.     gDialog.allFourBordersSame.removeAttribute("checked");
  777. }
  778.  
  779. // * Inits the values shown in the Background tab panel
  780. function InitBackgroundTabPanel()
  781. {
  782.   gDialog.selectedTab = BACKGROUND_TAB;
  783.   if (!gDialog.selectedObject || !gDialog.selectedObject.style)
  784.     return;
  785.  
  786.   gDialog.opacityScrollbar.removeEventListener("DOMAttrModified", onOpacityScrollbarAttrModified, false);
  787.   var opacity = getSpecifiedStyle("-moz-opacity");
  788.   if (opacity == "")
  789.     opacity = 1;
  790.   gDialog.opacityScrollbar.setAttribute("curpos", opacity*1000);
  791.   gDialog.opacityScrollbar.addEventListener("DOMAttrModified", onOpacityScrollbarAttrModified, false);
  792.   
  793.   /* INIT BACKGROUND-COLOR */
  794.   backgroundColor = ConvertRGBColorIntoHEXColor(getSpecifiedStyle("background-color"));
  795.   gDialog.backgroundColorInput.setAttribute("value", backgroundColor);
  796.   if (backgroundColor == "")
  797.     backgroundColor = "white";
  798.   setColorWell("backgroundCW", backgroundColor); 
  799.   AddStyleToElement(gDialog.backgroundPreview, "background-color", backgroundColor);
  800.  
  801.   /* INIT BACKGROUND-REPEAT */
  802.   var backgroundRepeat = getSpecifiedStyle("background-repeat");
  803.   var choice = "repeatBackgroundRepeatMenu";
  804.   if (backgroundRepeat == "no-repeat") {
  805.     choice = "norepeatBackgroundRepeatMenu";
  806.   }
  807.   else if (backgroundRepeat == "repeat-x") {
  808.     choice = "horizontallyBackgroundRepeatMenu";
  809.   }
  810.   else if (backgroundRepeat == "repeat-y") {
  811.     choice = "verticallyBackgroundRepeatMenu";
  812.   }
  813.   else if (backgroundRepeat == "repeat") {
  814.     choice = "repeatBackgroundRepeatMenu";
  815.   }
  816.   AddStyleToElement(gDialog.backgroundPreview, "background-repeat", backgroundRepeat);
  817.   var choiceItem = document.getElementById(choice);
  818.   gDialog.backgroundRepeatMenulist.selectedItem = choiceItem;
  819.  
  820.   /* INIT BACKGROUND-IMAGE */
  821.   var backgroundImage = getSpecifiedStyle("background-image");
  822.   gDialog.backgroundImageInput.setAttribute("value", backgroundImage);
  823.   enableBackgroundProps( (backgroundImage != "none" && backgroundImage != "") );
  824.   AddStyleToElement(gDialog.backgroundPreview, "background-image", backgroundImage);
  825.   
  826.   /* INIT BACKGROUND-ATTACHMENT */
  827.   var backgroundAttachment = getSpecifiedStyle("background-attachment");
  828.   gDialog.backgroundAttachmentCheckbox.checked = ( (backgroundAttachment == "fixed") ? false : true );
  829.   AddStyleToElement(gDialog.backgroundPreview, "background-attachment", backgroundAttachment);
  830.  
  831.   /* INIT BACKGROUND-POSITION */
  832.   var xBackgroundPosition = getSpecifiedStyle("-x-background-x-position");
  833.   var yBackgroundPosition = getSpecifiedStyle("-x-background-y-position");
  834.   var xRadio, yRadio;
  835.   if (xBackgroundPosition == "100%" || xBackgroundPosition == "right")
  836.     xRadio = "rightXBackgroundPositionRadio";
  837.   else if (xBackgroundPosition == "50%" || xBackgroundPosition == "center")
  838.     xRadio = "centerXBackgroundPositionRadio";
  839.   else
  840.     xRadio = "leftXBackgroundPositionRadio";
  841.   if (yBackgroundPosition == "100%" || yBackgroundPosition == "bottom")
  842.     yRadio = "bottomYBackgroundPositionRadio";
  843.   else if (xBackgroundPosition == "50%" || yBackgroundPosition == "center")
  844.     yRadio = "centerYBackgroundPositionRadio";
  845.   else
  846.     yRadio = "topYBackgroundPositionRadio";
  847.  
  848.   gDialog.xBackgroundPositionRadiogroup.selectedItem = document.getElementById(xRadio);
  849.   gDialog.yBackgroundPositionRadiogroup.selectedItem = document.getElementById(yRadio);
  850.   AddStyleToElement(gDialog.backgroundPreview, "background-attachment",
  851.                     xBackgroundPosition + " " + yBackgroundPosition);
  852. }
  853.  
  854. // * if the string |value| contains the substring |searchedString|, the
  855. //   checkbox of id |id| is checked ; it's unchecked otherwise.
  856. //   param String value
  857. //   param String searchedString
  858. //   param String id
  859. function SelectsCheckboxIfValueContains(value, searchedString, id)
  860. {
  861.   if (checkbox) {
  862.     var state = (value.indexOf(searchedString) != -1);
  863.     var checkbox = document.getElementById(id);
  864.     checkbox.checked = state;
  865.   }
  866. }
  867.  
  868. // * First, if |xulElt| is not null, this function copies the
  869. //   specified style for the CSS property |property| to the inline
  870. //   styles carried by |xulElt|. Then it retrieves the property's
  871. //   value, remove possible dashes, and append |idSuffix| to it.
  872. //   It forms the ID of a menu item that will be selected in the
  873. //   menulist |idMenuList|.
  874. //   param String property
  875. //   param String idMenuList
  876. //   param String idSuffix
  877. //   param XULElement xulElt
  878. function SelectsOneChoice(property, idMenulist, idSuffix, xulElt)
  879. {
  880.   var propertyValue = getSpecifiedStyle(property);
  881.   if (xulElt) {
  882.     AddStyleToElement(xulElt, property, propertyValue);
  883.   }
  884.   propertyValue = TrimDashes(propertyValue);
  885.   var menulist = document.getElementById(idMenulist);
  886.   var choice = "unspecified" + idSuffix;
  887.   if (propertyValue && propertyValue != "") {
  888.     choice = propertyValue + idSuffix;
  889.   }
  890.   var choiceItem = document.getElementById(choice);
  891.   menulist.selectedItem = choiceItem;
  892. }
  893.  
  894. // * utility function to convert predefined HTML4 color names
  895. //   into their #rrggbb equivalent
  896. //   param String color
  897. //   return String
  898. function getHexColorFromColorName(color)
  899. {
  900.   var namedColorsArray = [
  901.     { name:"aqua",     value:"#00ffff" },
  902.     { name:"black",    value:"#000000" },
  903.     { name:"blue",     value:"#0000ff" },
  904.     { name:"fuchsia",  value:"#ff00ff" },
  905.     { name:"gray",     value:"#808080" },
  906.     { name:"green",    value:"#008000" },
  907.     { name:"lime",     value:"#00ff00" },
  908.     { name:"maroon",   value:"#800000" },
  909.     { name:"navy",     value:"#000080" },
  910.     { name:"olive",    value:"#808000" },
  911.     { name:"purple",   value:"#800080" },
  912.     { name:"red",      value:"#ff0000" },
  913.     { name:"silver",   value:"#c0c0c0" },
  914.     { name:"teal",     value:"#008080" },
  915.     { name:"white",    value:"#ffffff" },
  916.     { name:"yellow",   value:"#ffff00" }
  917.     ];
  918.   for (var i=0; i< namedColorsArray.length; i++) {
  919.     if (color == namedColorsArray[i].name) {
  920.       color = namedColorsArray[i].value;
  921.       break;
  922.     }
  923.   }
  924.   return color;
  925. }
  926.  
  927. // * retrieve the specified value for the CSS property |property|.
  928. //   The beauty of the CSS OM is that the same exact function can be
  929. //   used for both inline styles carried by an element, and rules in a
  930. //   stylesheet
  931. //   param String property
  932. //   return String
  933. function getSpecifiedStyle(property)
  934. {
  935.   if (gDialog.selectedObject && gDialog.selectedObject.style) {
  936.     return gDialog.selectedObject.style.getPropertyValue(property).toLowerCase();
  937.   }
  938.  
  939.   return null;
  940. }
  941.  
  942. // * This recreates the textual content of an embedded stylesheet
  943. //   param DOMCSSStyleSheet sheet
  944. function SerializeEmbeddedSheet(sheet)
  945. {
  946.   var ownerNode = sheet.ownerNode;
  947.   var cssText = "\n";
  948.   var l = sheet.cssRules.length;
  949.   var tmp;
  950.   for (var j = 0; j< l; j++) {
  951.     tmp = sheet.cssRules.item(j).cssText;
  952.     var re = /;\s*/;
  953.     var cssTextSplitted = tmp.split(re);
  954.     cssText += "  ";
  955.     for (var k=0; k<cssTextSplitted.length; k++) {
  956.       cssText += cssTextSplitted[k];
  957.       if (k != cssTextSplitted.length-1)
  958.         cssText += ";\n    ";
  959.     }
  960.     if (l > 1) cssText += "\n\n";
  961.   }
  962.   var child = ownerNode.lastChild;
  963.   while (child) {
  964.     tmp = child.previousSibling;
  965.     ownerNode.removeChild(child);
  966.     child = tmp;
  967.   }
  968.   var textNode = document.createTextNode(cssText + "\n");
  969.   ownerNode.appendChild(textNode);
  970. }
  971.  
  972. // * This recreates the textual content of an external stylesheet
  973. //   param DOMCSSStyleSheet sheet
  974. //   param String href
  975. function SerializeExternalSheet(sheet, href)
  976. {
  977.   const classes             = Components.classes;
  978.   const interfaces          = Components.interfaces;
  979.   const nsILocalFile        = interfaces.nsILocalFile;
  980.   const nsIFileOutputStream = interfaces.nsIFileOutputStream;
  981.   const FILEOUT_CTRID       = '@mozilla.org/network/file-output-stream;1';
  982.   
  983.   var fileHandler = GetFileProtocolHandler();
  984.   var localFile;
  985.   if (href)
  986.     localFile = fileHandler.getFileFromURLSpec(href).QueryInterface(nsILocalFile);
  987.   else
  988.     localFile = fileHandler.getFileFromURLSpec(sheet.href).QueryInterface(nsILocalFile);
  989.  
  990.   var fileOuputStream = classes[FILEOUT_CTRID].createInstance(nsIFileOutputStream);
  991.   try {
  992.     fileOuputStream.init(localFile, -1, -1, 0);
  993.  
  994.     var cssText = "/* Generated by CaScadeS, a stylesheet editor for Mozilla Composer */\n\n";
  995.     var l = sheet.cssRules.length, tmp;
  996.     var re = /;\s*/;
  997.     var cssTextSplitted, ruleIndex, singleDeclIndex;
  998.     
  999.     for (ruleIndex = 0; ruleIndex< l; ruleIndex++) {
  1000.       tmp = sheet.cssRules.item(ruleIndex).cssText;
  1001.       cssTextSplitted = tmp.split(re);
  1002.       cssText += "  ";
  1003.       for (singleDeclIndex=0; singleDeclIndex<cssTextSplitted.length; singleDeclIndex++) {
  1004.         cssText += cssTextSplitted[singleDeclIndex];
  1005.         if (singleDeclIndex != cssTextSplitted.length-1)
  1006.           cssText += ";\n    ";
  1007.       }
  1008.       if (l > 1) cssText += "\n\n";
  1009.     }
  1010.     var textNode = document.createTextNode(cssText + "\n");
  1011.     fileOuputStream.write(cssText, cssText.length);
  1012.     fileOuputStream.close();
  1013.   }
  1014.   catch (ex) {}
  1015. }
  1016.  
  1017. // * if the checkbox of ID |checkboxID| is checked, copies the value |value|,
  1018. //   supposed to be the one for the top side, to the other three sides, makes
  1019. //   the XUL Element |elt| have that value. |propertyBase| and |propertySuffix|
  1020. //   are used to create side properties like in border-*-style.
  1021. //   The property and value are also added to the styles of the element of ID
  1022. //   |previewID| if it not null.
  1023. //   param String propertyBase
  1024. //   param String propertySuffix
  1025. //   param String value
  1026. //   param String checkboxID
  1027. //   param String previewID
  1028. //   param XULElement elt
  1029. function IfFourSidesSameStyle(propertyBase, propertySuffix, value, checkboxID, previewID, elt)
  1030. {
  1031.   // value is the value of the '*-top' property
  1032.   var checkbox = document.getElementById(checkboxID);
  1033.   if (!checkbox || !checkbox.checked) return;
  1034.  
  1035.   if (!value) {
  1036.     if (elt) {
  1037.       value = elt.value;
  1038.     }
  1039.   }
  1040.   var xulElt = document.getElementById(previewID);
  1041.   var sideArray = [ "left", "right", "bottom" ];
  1042.   for (var i=0; i<sideArray.length; i++) {
  1043.     var property = propertyBase + "-" + sideArray[i] + "-" + propertySuffix;
  1044.     if (xulElt) {
  1045.       AddStyleToElement(xulElt, property, value);
  1046.     }
  1047.     AddStyleToElement(gDialog.selectedObject, property, value);
  1048.   }
  1049. }
  1050.  
  1051. // * Callback when the user clicks on the "use same style for
  1052. //   the four borders" checkbox. |elt| is that checkbox.
  1053. //   param XULElement elt
  1054. function ToggleFourBorderSidesSameStyle(elt)
  1055. {
  1056.   var sameStyle = elt.checked;
  1057.   var sideArray = [ "left", "right", "bottom" ];
  1058.  
  1059.   var style = getSpecifiedStyle("border-top-style");
  1060.   if (!sameStyle && !style)
  1061.     style = "unspecified";
  1062.   var color = gDialog.topBorderColorInput.value;
  1063.   var width = getSpecifiedStyle("border-top-width");
  1064.  
  1065.   for (var i=0; i<sideArray.length; i++) {
  1066.     var styleMenulist = document.getElementById( sideArray[i] + "BorderStyleMenulist" );
  1067.     var widthInput    = document.getElementById( sideArray[i] + "BorderWidthInput" );
  1068.     var colorInput    = document.getElementById( sideArray[i] + "BorderColorInput" );
  1069.     var colorButton   = document.getElementById( sideArray[i] + "BorderColorButton" );
  1070.     if (sameStyle) {
  1071.       styleMenulist.selectedItem = document.getElementById("unspecified" + sideArray[i] + "BorderStyle");
  1072.  
  1073.       widthInput.value = "";
  1074.  
  1075.       colorInput.value = "";
  1076.       colorInput.setAttribute("disabled", "true");
  1077.       setColorWell("border"+sideArray[i]+"CW", "");
  1078.  
  1079.       widthInput.setAttribute("disabled", "true");
  1080.       styleMenulist.setAttribute("disabled", "true");
  1081.       colorButton.setAttribute("disabled", "true");
  1082.  
  1083.       AddStyleToElement(gDialog.borderPreview, "border-"+sideArray[i]+"-color", color);
  1084.       AddStyleToElement(gDialog.borderPreview, "border-"+sideArray[i]+"-style", style);
  1085.       AddStyleToElement(gDialog.borderPreview, "border-"+sideArray[i]+"-width", width);
  1086.  
  1087.       AddStyleToElement(gDialog.selectedObject, "border-"+sideArray[i]+"-color", color);
  1088.       AddStyleToElement(gDialog.selectedObject, "border-"+sideArray[i]+"-style", style);
  1089.       AddStyleToElement(gDialog.selectedObject, "border-"+sideArray[i]+"-width", width);
  1090.     }
  1091.     else {
  1092.       styleMenulist.removeAttribute("disabled");
  1093.       widthInput.removeAttribute("disabled");
  1094.       colorInput.removeAttribute("disabled");
  1095.       colorButton.removeAttribute("disabled");
  1096.  
  1097.       colorInput.value = color;
  1098.       setColorWell("border"+sideArray[i]+"CW", color);
  1099.       widthInput.value = width;
  1100.       var styleMenuitem = document.getElementById( style+sideArray[i]+"BorderStyle" );
  1101.       styleMenulist.selectedItem = styleMenuitem;
  1102.     }
  1103.   }
  1104. }  
  1105.  
  1106. // * Enable a XUL element depending on a boolean value
  1107. //   param XULElement elt
  1108. //   param boolean enabled
  1109. function EnableUI(elt, enabled)
  1110. {
  1111.   if (enabled) {
  1112.     elt.removeAttribute("disabled");
  1113.   }
  1114.   else {
  1115.     elt.setAttribute("disabled", "true");
  1116.   }
  1117. }
  1118.  
  1119. // * Initializes a menupopup containing length units. It looks for
  1120. //   the current value of the property and if it is already a length,
  1121. //   build the menu keeping the same numeric part and browsing all the
  1122. //   possible units.
  1123. function InitLengthUnitMenuPopup(elt, property, id, allowsPercentages)
  1124. {
  1125.   var value = elt.parentNode.value;
  1126.   var re = /([+-]?\d*\.\d+|[+-]?\d+)\D*/ ;
  1127.   var found = value.match(re);
  1128.   var numPart = "0";
  1129.   if (found && found.length != 0)
  1130.     numPart = RegExp.$1;
  1131.  
  1132.   var child = elt.firstChild, tmp;
  1133.   while (child && child.nodeName.toLowerCase() != "menuseparator") {
  1134.     tmp = child.nextSibling;
  1135.     elt.removeChild(child);
  1136.     child = tmp;
  1137.   }
  1138.  
  1139.   // below is an array of all valid CSS length units
  1140.   var unitsArray = [ "%", "px", "pt", "cm", "in", "mm", "pc", "em", "ex" ];
  1141.   var j, newitem, start = 0;
  1142.   if (!allowsPercentages)
  1143.     start = 1;
  1144.   for (j=start; j<unitsArray.length; j++) {
  1145.     var itemValue = numPart + unitsArray[j];
  1146.     newitem = document.createElementNS(XUL_NS, "menuitem");
  1147.     newitem.setAttribute("label", itemValue);
  1148.     newitem.setAttribute("value", itemValue);
  1149.     if (child)
  1150.       elt.insertBefore(newitem, child);
  1151.     else
  1152.       elt.appendChild(newitem);
  1153.   }
  1154. }
  1155.  
  1156. // * Removes all dashes from a string
  1157. //   param String s
  1158. //   return String
  1159. function TrimDashes(s)
  1160. {
  1161.   var r = "", i;
  1162.   for (i=0; i<s.length; i++)
  1163.     if (s[i] != '-')
  1164.       r += s[i];
  1165.   return r;
  1166. }
  1167.  
  1168. // * Callback for spinbuttons. Increments of |increment| the length value of
  1169. //   the XUL element of ID |id|.
  1170. //   param integer increment
  1171. //   param String id
  1172. function Spinbutton(increment, id)
  1173. {
  1174.   var elt = document.getElementById(id);
  1175.   if (elt) {
  1176.     var value = elt.value;
  1177.     var re = /([+-]?\d*\.\d+|[+-]?\d+)(\D*)/ ;
  1178.     var found = value.match(re);
  1179.     if (found && found.length != 0) {
  1180.       var numPart = RegExp.$1;
  1181.       var unitPart = RegExp.$2;
  1182.       var unitIncrement;
  1183.       switch (unitPart) {
  1184.         case "cm":
  1185.         case "in":
  1186.           unitIncrement = 0.01;
  1187.           break;
  1188.         default:
  1189.           unitIncrement = 1;
  1190.           break;
  1191.       }
  1192.       elt.value = (Math.round(100 * (parseFloat(numPart) + (increment * unitIncrement)))/100) + unitPart;
  1193.     }
  1194.     else
  1195.       elt.value = increment + "px";
  1196.     elt.oninput();
  1197.   }
  1198. }
  1199.  
  1200. // * code for initLocalFontFaceMenu shamelessly stolen from
  1201. //   Charley Manske <cmanske@netscape.com>
  1202. //   param XULElement menuPopup
  1203. function initLocalFontFaceMenu(menuPopup)
  1204. {
  1205.   if (!menuPopup) return;
  1206.   var menu = menuPopup.parentNode;
  1207.   if (!gLocalFonts)
  1208.   {
  1209.     // Build list of all local fonts once per editor
  1210.     try 
  1211.     {
  1212.       var enumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"].createInstance();
  1213.       if( enumerator )
  1214.         enumerator = enumerator.QueryInterface(Components.interfaces.nsIFontEnumerator);
  1215.       var localFontCount = { value: 0 }
  1216.       var localFontsString = enumerator.EnumerateAllFonts(localFontCount);
  1217.       if (localFontsString)
  1218.         gLocalFonts = localFontsString.toString().split(",");
  1219.       if (gLocalFonts)
  1220.       {
  1221. //        faces.sort(); Array is already sorted
  1222.         for( var i = 0; i < gLocalFonts.length; i++ )
  1223.         {
  1224.           if( gLocalFonts[i] != "" )
  1225.           {
  1226.             var itemNode = document.createElement("menuitem");
  1227.             itemNode.setAttribute("label", gLocalFonts[i]);
  1228.             //itemNode.value = gLocalFonts[i];
  1229.             itemNode.setAttribute("value", gLocalFonts[i]);
  1230.             menuPopup.appendChild(itemNode);
  1231.           }
  1232.         }
  1233.       }
  1234.     }
  1235.     catch(e) { }
  1236.   }
  1237.   //SetElementEnabledById("localFontFaceMenu", gLocalFonts != 0);
  1238. }
  1239.  
  1240. // * Handles a command in a menulist
  1241. //   param XULElement elt
  1242. //   param String property
  1243. //   param String id
  1244. function DoMenulistCommand(elt, property, id) {
  1245.   var choice = elt.selectedItem;
  1246.   var value = choice.value;
  1247.   onPullDownChanged(property, value, id);
  1248.   if (property == "border-top-style") {
  1249.     // this one is a special case : we need to check if the checkbox
  1250.     // "all sides have same style" is checked ; if it's checked, make
  1251.     // the other 3 sides acquire the style assigned to the top border
  1252.     IfFourSidesSameStyle('border', 'style', value,
  1253.                          'allFourBordersSame', id, null);
  1254.   }
  1255. }
  1256.  
  1257.